﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using Atmk.WaterMeter.MIS.Commons;
using Atmk.WaterMeter.MIS.Commons.Interfaces;
using Atmk.WaterMeter.MIS.Commons.Interfaces.Logic;
using Atmk.WaterMeter.MIS.Commons.Interfaces.Logic.Statistics;
using Atmk.WaterMeter.MIS.Commons.Interfaces.Repository;
using Atmk.WaterMeter.MIS.Commons.Utils;
using Atmk.WaterMeter.MIS.Datas;
using Atmk.WaterMeter.MIS.Entities;
using Atmk.WaterMeter.MIS.Entities.Enums;
using Atmk.WaterMeter.MIS.Entities.Models;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace Atmk.WaterMeter.MIS.Logic
{
    /// <summary>
    /// 查询所有数据
    /// </summary>
    public class QueryDatasLogic : IQueryDatasLogic
    {
        private static readonly NLog.Logger _logger = NLog.LogManager.GetCurrentClassLogger();

        private List<Owner> _Owners;
        private List<Meter> _Meters;
        private List<MeterReadingRecord> _MeterReadingRecords;
        private List<District> _Districts;

        public Token Token { get; set; }
        public string DistrictId { get; set; }
        public string SearchType { get; set; }
        public string SearchValue { get; set; }


        private readonly IRepository _repository;
        private readonly IBaseInfoLogic _baseInfoLogic;
        private readonly IDistrictLogic _districtLogic;
        private readonly IDistrictRepository _districtRepository;


        public QueryDatasLogic(
            IRepository repository,
            IBaseInfoLogic baseInfoLogic,
            IDistrictLogic districtLogic,
            IDistrictRepository districtRepository
        )
        {
            _repository = repository;
            _baseInfoLogic = baseInfoLogic;
            _districtLogic = districtLogic;
            _districtRepository = districtRepository;
        }

        /// <summary>
        /// 执行方法前，设置通用数据
        /// </summary>
        private void QueryDatasSet()
        {
            QueryDatas(Token, DistrictId, SearchType, SearchValue);
        }

        /// <summary>
        /// 查询所有抄表记录或查询最新抄表记录
        /// </summary>
        /// <param name="token"></param>
        /// <param name="aid"></param>
        /// <param name="count"></param>
        /// <param name="searchType"></param>
        /// <param name="searchValue"></param>
        private void QueryDatas(Token token, string aid, string searchType = "", string searchValue = "")
        {
            //第一步 获取所有用户信息
            // var districtlist = Enumerable.ToList<District>(_repository.FindAll<District>());
            //获取主区域及下所有子区域信息
            //var districts =_districtLogic.GetDistrictsByUid(token.payload.id, districtlist);

            var districts = _districtRepository.GetBaseDistrictEntities(token.payload.areaid, aid);

            //if (!string.IsNullOrEmpty(aid))
            //{
            //    districts =_districtLogic.DistrictEntitiesById(aid, districtlist);
            //}
            _Districts = districts;
            //获取业主信息
            var owners = Enumerable.Where<Owner>(_repository.FindAll<Owner>(), o =>
                    districts.Select(d => d.Id.ToString()).Contains(o.DistrictId) &&
                    o.RecordState == (int)RecordStateEnum.Normal)
                .ToList();
            //条件筛选
            _Owners = _baseInfoLogic.QuerySearchOwner(searchType, searchValue, owners);
            //获取水表信息
            var meters = Enumerable.Where<Meter>(_repository.FindAll<Meter>(),
                    m => _Owners.Select(o => o.Id.ToString()).Contains(m.OwnerId) && m.RecordState == (int)RecordStateEnum.Normal)
                .ToList();
            _Meters = _baseInfoLogic.QuerySearchMeter(searchType, searchValue, meters);
            if (_Meters.Count != 0 && _Owners.Count != 0)
                //获取抄表记录
                _MeterReadingRecords = _repository.FindAll<MeterReadingRecord>().Where(r =>
                    _Meters.Select(m => m.MeterNumber).Contains(r.CtdeviceId)).ToList();
            else
            {
                _MeterReadingRecords = new List<MeterReadingRecord>();
            }
        }

        /// <summary>
        /// 获取抄表数据
        /// </summary>
        /// <param name="page"></param>
        /// <param name="pageSize"></param>
        /// <param name="dateType"></param>
        /// <param name="sTime"></param>
        /// <param name="eTime"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        public object SelectMeterDates(Token token, string aid,string searchType, string searchValue, int page, int pageSize, string dateType, DateTime sTime, DateTime eTime,out int count)
        {
            try
            {
                var meterReadingRecords = new List<MeterReadingRecord>();
                string meterCtdeviceId = string.Empty;
                using (var _context = ContextBuilder.Build())
                {
                    if (string.IsNullOrWhiteSpace(searchValue))
                    {
                        var district = _context.District.Where(m => m.ProjectId == token.payload.areaid && m.NodeType == 2).FirstOrDefault();
                        var districts_id = !string.IsNullOrWhiteSpace(aid) ? aid : district.Id;
                        var total_owners = _context.Owner.Where(o => districts_id == o.DistrictId).ToList();
                        var total_meters = _context.Meter.Where(m => m.MeterState == "建档" && districts_id == m.DistrictId).ToList();
                        var total_meter_ids = total_meters.Select(m => m.CtdeviceId);
                        meterReadingRecords = _context.MeterReadingRecord.Where(m => m.ReadTime.Date >= sTime.Date && m.ReadTime.Date <= eTime.Date&& total_meter_ids.Contains(m.CtdeviceId)).ToList();


                    }
                    else
                    {
                        switch (searchType)
                        {
                            case "表编号":
                                if (_context.Meter.FirstOrDefault(m => m.MeterNumber.Contains(searchValue)) == null)
                                {
                                    count = 0;
                                    return new List<object>();
                                }
                                else
                                {
                                    meterCtdeviceId = _context.Meter.First(m => m.MeterNumber.Contains(searchValue)).CtdeviceId;
                                }
                                break;
                            case "门牌号":
                                string ownerId = _context.Owner.FirstOrDefault(m => m.HouseNumber.Contains(searchValue))?.Id.ToString();
                                if (!string.IsNullOrWhiteSpace(ownerId))
                                {
                                    meterCtdeviceId = _context.Meter.FirstOrDefault(m => m.OwnerId == ownerId)?.MeterNumber;
                                }
                                break;
                            case "业主姓名":
                                ownerId = _context.Owner.FirstOrDefault(m => m.Name.Contains(searchValue))?.Id.ToString();
                                if (!string.IsNullOrWhiteSpace(ownerId))
                                {
                                    meterCtdeviceId = _context.Meter.FirstOrDefault(m => m.OwnerId == ownerId)?.CtdeviceId;
                                }
                                break;
                            case "手机号":
                                ownerId = _context.Owner.FirstOrDefault(m => m.Mobile.Contains(searchValue))?.Id.ToString();
                                if (string.IsNullOrWhiteSpace(ownerId))
                                {
                                    count = 0;
                                    return new List<object>();
                                }
                                else
                                {
                                    meterCtdeviceId = _context.Meter.FirstOrDefault(m => m.OwnerId == ownerId)?.CtdeviceId;
                                }
                                break;
                        }
                        meterReadingRecords = _context.MeterReadingRecord.Where(m => m.ReadTime.Date >= sTime.Date && m.ReadTime.Date <= eTime.Date && meterCtdeviceId == m.CtdeviceId).ToList();
                    }

                    var list_page = meterReadingRecords.OrderByDescending(m => m.ReadTime).Skip((page - 1) * pageSize).Take(pageSize).ToList();
                    var list = new List<object>();
                    switch (dateType)
                    {
                        case "当前数据":
                            list = SelectMeterDates_Tools_doForeach(list_page, _context.Meter.Where(m=>m.ProjectId==token.payload.areaid).ToList(), _context.Owner.ToList(),_context.District.ToList());
                            break;
                        case "日冻结数据":
                            //meterReads = meterReads.Where(m => (int)m.Value24Type == 2).OrderByDescending(m => m.ReadTime);
                            //list = SelectMeterDates_Tools_doForeach(meterReads, total_meters, total_owners, total_districts);
                            break;
                        default:
                            //全查
                            //meterReads = meterReads.OrderByDescending(m => m.ReadTime);
                            //list = SelectMeterDates_Tools_doForeach(meterReads, total_meters, total_owners, total_districts);
                            //break;
                            list = SelectMeterDates_Tools_doForeach(list_page, _context.Meter.Where(m => m.ProjectId == token.payload.areaid).ToList(), _context.Owner.ToList(), _context.District.ToList());
                            break;
                    }
                    count = meterReadingRecords.Count();
                    //获取分页数据

                    return list;
                }
            }
            catch (Exception e)
            {
                _logger.Error(e);
                throw new Exception(e.Message, e);
            }
        }
        public List<object> SelectMeterDates_Tools_doForeach(List<MeterReadingRecord> meterReads, List<Meter> meters, List<Owner> owners, List<District> districts)
        {
            var list = new List<object>();
            foreach (var item in meterReads)
            {
                var meter = meters.FirstOrDefault(m => m.CtdeviceId == item.CtdeviceId);
                if (meter==null)
                {
                    continue;
                }
                var owner = owners.FirstOrDefault(o => o.Id.ToString() == meter.OwnerId);
                list.Add(new
                {
                    districtName = owner==null? "空":districts.FirstOrDefault(m=> m.Id==owner.DistrictId)?.Name,
                    ownerId = owner?.Id.ToString(),
                    ownerName = owner?.Name, //业主名称
                    houseNumber = owner?.HouseNumber, //门牌号   
                    meterType = meter?.MeterType, //表类型
                    meterNumber = meter?.MeterNumber, //表编号
                    meterValue = item.Value, //当前读数/日冻结数据/月冻结数据/冻结数(抄表历史数据)
                    cellVoltage = item.Voltage, //电池电压： 只有当前数据和历史数据有显示
                    Warning = item.Warning == null ? "" : (item.Warning == 0 ? "正常" : "异常"),//报警状态
                    tapStatus = Tools.ValveStatic(item.ValveState), //阀门状态
                    readTime = item.ReadTime.ToString("yyyy-MM-dd HH:mm:ss"), //抄表时间
                    //Value24Type = Tools.Value24Type(item.Value24Type)
                });
            }
            return list;
        }
        public static string GetDescription(Enum en)
        {
            Type type = en.GetType();   //获取类型
            MemberInfo[] memberInfos = type.GetMember(en.ToString());   //获取成员
            if (memberInfos != null && memberInfos.Length > 0)
            {
                DescriptionAttribute[] attrs = memberInfos[0].GetCustomAttributes(typeof(DescriptionAttribute), false) as DescriptionAttribute[];   //获取描述特性

                if (attrs != null && attrs.Length > 0)
                {
                    return attrs[0].Description;    //返回当前描述
                }
            }
            return en.ToString();
        }


        /// <summary>
        /// 查询指定日期未抄回数据表
        /// </summary>
        /// <param name="page"></param>
        /// <param name="pageSize"></param>
        /// <param name="dateType"></param>
        /// <param name="meterType"></param>
        /// <param name="date"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        public object SelectNoDatesMeter(int page, int pageSize, string dateType, string meterType, DateTime date,
            out int count)
        {
            QueryDatasSet();
            //获取选定日期抄表记录
            var month = dateType.Contains("月冻结");
            var meterReads = _MeterReadingRecords.Where(m => SameDate(month, m.ReadTime.Date, date.Date)).ToList();
            var meterReadCodes = meterReads.Select(m => m.CtdeviceId).ToList();
            var list = new List<object>();
            var meters = _Meters.Where(m => !meterReadCodes.Contains(m.MeterNumber)).ToList();
            foreach (var meter in meters)
            {
                var owner = _Owners.First(o => o.Id.ToString() == meter.OwnerId);
                var district = _Districts.First(d => d.Id.ToString() == owner.DistrictId);
                list.Add(new
                {
                    districtName = district.Name,
                    ownerId = owner.Id.ToString(),
                    ownerName = owner.Name, //业主名称
                    houseNumber = owner.HouseNumber, //门牌号   
                    meterType = meter.MeterType, //表类型
                    meterNumber = meter.MeterNumber //表编号
                });
            }
            var newlist = list.OrderBy(f => JObject.Parse(JsonConvert.SerializeObject(f))["houseNumber"]).ToList();
            count = newlist.Count;
            //获取分页数据
            var result = PaginatedList<object>.Create(newlist, page, pageSize);

            return result;
        }

        private bool SameDate(bool month, DateTime read, DateTime date)
        {
            if (month)
            {
                return read.Year == date.Year && read.Month == date.Month;
            }
            return read.Date == date.Date;
        }

        private bool GreatDate(bool month, DateTime bigTime, DateTime littleTime)
        {
            if (month)
            {
                return bigTime.Year >= littleTime.Year && bigTime.Month >= littleTime.Month;
            }
            return bigTime.Date >= littleTime.Date;
        }

        /// <summary>
        /// 获取平局用水量
        /// </summary>
        /// <param name="page"></param>
        /// <param name="pageSize"></param>
        /// <param name="statisticsType"></param>
        /// <param name="useageGreat"></param>
        /// <param name="useageLess"></param>
        /// <param name="sTime"></param>
        /// <param name="eTime"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        public object SelectWaterDosage(int page, int pageSize, int statisticsType, int useageGreat, int useageLess,
            DateTime sTime, DateTime eTime, out int count)
        {
            try
            {
                //QueryDatasSet();  完全没用 影响效率的代码

                //获取指定时间内水表记录信息
                //var meterReads = _MeterReadingRecords
                //    .Where(m => GreatDate(month, m.ReadTime.Date, sTime.Date) &&
                //                GreatDate(month, eTime.Date, m.ReadTime.Date)).ToList();
                var month = statisticsType == 1;
                using (var context = Datas.ContextBuilder.Build())
                {
                    #region 旧版低性能 代码备份
                    //var groupMr = context.MeterReadingRecords.Where(m => m.ReadTime.Date> sTime &&
                    //           m.ReadTime.Date < eTime.Date).GroupBy(m => m.Number);

                    //var tsp = eTime - sTime;
                    //var months = (eTime.Date.Year - sTime.Year) * 12 + (eTime.Month - sTime.Month) + 1;

                    //foreach (var item in groupMr)
                    //{
                    //    var meterNumber = item.Key;
                    //    var meter = _Meters.First(m => m.MeterNumber == meterNumber);
                    //    var owner = _Owners.First(o => o.Id.ToString() == meter.OwnerId);
                    //    var district = _Districts.First(d => d.Id.ToString() == owner.DistrictId);
                    //    var meterRecords = item.OrderBy(r => r.ReadTime).ToList();
                    //    var avage = (decimal)meterRecords.Sum(r => r.Value - r.LastValue) / (month ? tsp.Days : months);
                    //    list.Add(new
                    //    {
                    //        districtName = district.Name,
                    //        ownerId = owner.Id.ToString(),
                    //        ownerName = owner.Name, //业主名称
                    //        houseNumber = owner.HouseNumber, //门牌号   
                    //        meterType = meter.MeterType, //表类型
                    //        meterNumber = meter.MeterNumber, //表编号
                    //        startTime = meterRecords.First().ReadTime.ToString(month ? "yyyy-MM" : "yyyy-MM-dd"),
                    //        endTime = meterRecords.Last().ReadTime.ToString(month ? "yyyy-MM" : "yyyy-MM-dd"),
                    //        useageAvage = decimal.Round(avage, 2),
                    //    });
                    //} 
                    #endregion
                    var list = new List<object>();
                    var districts = context.District.Where(m => m.ProjectId == Token.payload.areaid).ToList();
                    var owners = context.Owner.Where(m => districts.Select(m1 => m1.Id.ToString()).Contains(m.DistrictId)).ToList();
                    switch (SearchType)
                    {
                        case "门牌号":
                            owners = owners.Where(m => m.HouseNumber.Contains(SearchValue)).ToList();
                            break;
                        case "业主姓名":
                            owners = owners.Where(m => m.Name.Contains(SearchValue)).ToList();
                            break;
                        case "手机号":
                            owners = owners.Where(m => m.Mobile.Contains(SearchValue)).ToList();
                            break;
                    }
                    var meters = context.Meter.Where(m => owners.Select(m1 => m1.Id.ToString()).Contains(m.OwnerId)).ToList();
                    switch (SearchType)
                    {
                        case "表编号":
                            meters = meters.Where(m => m.MeterNumber.Contains(SearchValue)).ToList();
                            break;
                    }
                    //取开始 到 结束日期内的 数据  
                    var meterReadingRecords = context.MeterReadingRecord.Where(m => m.ReadTime.Date > sTime && m.ReadTime.Date < eTime.Date
                    && meters.Select(m1 => m1.MeterNumber).Contains(m.CtdeviceId)).ToList();

                    foreach (var meter in meters)
                    {
                        var owner = owners.FirstOrDefault(m => m.Id.ToString() == meter.OwnerId);
                        var meterReadingRecords_filter = meterReadingRecords.Where(m => m.CtdeviceId == meter.MeterNumber).OrderByDescending(m => m.ReadTime)
                            .GroupBy(m => m.ReadTime.ToString("yyyyMMdd")).Select(m => m.First());

                        list.Add(new
                        {
                            districtName = districts.FirstOrDefault(m => m.Id.ToString() == owner.DistrictId)?.Name,
                            ownerId = owner.Id.ToString(),
                            ownerName = owner.Name, //业主名称
                            houseNumber = owner.HouseNumber,//门牌号   
                            meterType = meter?.MeterType, //表类型
                            meterNumber = meter?.MeterNumber,//表编号
                            endTime = meterReadingRecords_filter.Any() ? meterReadingRecords_filter.First().ReadTime.ToString(month ? "yyyy-MM" : "yyyy-MM-dd") : "",
                            startTime = meterReadingRecords_filter.Any() ? meterReadingRecords_filter.Last().ReadTime.ToString(month ? "yyyy-MM" : "yyyy-MM-dd") : "",
                            useageAvage = meterReadingRecords_filter.Any() ? meterReadingRecords_filter.Average(m => m.Value).ToString("f2") : "",
                            //total_value = String.Format("{0:F}", meterReadingRecords_filter.Sum(m => m.Value)),
                            total_value = meterReadingRecords_filter.Any() ? meterReadingRecords_filter.First().Value.ToString("f2") : "",
                        });
                    }
                    count = list.Count;
                    //获取分页数据
                    //var result = PaginatedList<object>.Create(list, page, pageSize);
                    var result = PaginatedList<object>.Create(list, page, pageSize);
                    return result;
                }
            }
            catch (Exception ex)
            {
                _logger.Info("日平均用量错误信息：" + ex.ToString());
                count = 0;
                return PaginatedList<object>.Create(new List<object>(), page, pageSize);
            }
        }

        /// <summary>
        /// 获取最新的水表上报记录
        /// </summary>
        /// <param name="meterNumber"></param>
        /// <returns></returns>
        public MeterReadingRecord SelectNearRecord(string meterNumber)
        {
            //获取最新水表数据
            var meters = _repository.FindAll<MeterReadingRecord>()
                //.Where(m => m.Number == meterNumber)
                .OrderByDescending(r => r.ReadTime).ToList();
            return meters.Any() ? meters.First() : new MeterReadingRecord() { };
        }
    }
}